package com.bstek.uflo.form.action.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.hibernate.Session;
import org.hibernate.jdbc.Work;

import com.bstek.dorado.view.View;
import com.bstek.uflo.form.Constants;
import com.bstek.uflo.form.action.Action;
import com.bstek.uflo.form.action.FormData;
import com.bstek.uflo.form.model.TableColumn;
import com.bstek.uflo.form.model.TableDefinition;
import com.bstek.uflo.form.view.common.FormState;
import com.bstek.uflo.utils.EnvironmentUtils;
import com.bstek.uflo.utils.IDGenerator;

/**
 * @author Jacky.gao
 * @since 2013年11月12日
 */
public class SaveFormDataAction implements Action {
	public String getName() {
		return "保存数据";
	}

	public String getIcon() {
		return "url(skin>common/icons.gif) -140px -20px";
	}

	public void onViewInit(View view) {
	}

	public void execute(FormData formData, Session session) {
		saveFormData(formData, session);
	}
	
	protected String saveFormData(final FormData formData,Session session){
		final String[] returnValues=new String[1];
		session.doWork(new Work(){
			public void execute(Connection connection) throws SQLException {
				Map<String,Object> map=formData.getMasterTable();
				TableDefinition table=formData.getTable();
				String sql=null;
				List<Object> params=new ArrayList<Object>();
				Object primaryKeyValue=map.get(Constants.PRIMARY_KEY_COLUMN);
				if(primaryKeyValue==null || primaryKeyValue.toString().equals("0")){
					primaryKeyValue=IDGenerator.getInstance().nextId();
					//map.put(Constants.PRIMARY_KEY_COLUMN,primaryKeyValue);
					params.add(primaryKeyValue);
					sql=buildInsertSql(table,params,map,null);
				}else{
					sql=buildUpdateSql(table,params,map);
				}
				returnValues[0]=primaryKeyValue.toString();
				PreparedStatement stmt=connection.prepareStatement(sql);
				for(int i=1;i<params.size()+1;i++){
					Object obj=params.get(i-1);
					stmt.setObject(i,obj);
				}
				stmt.execute();
				stmt.close();
				saveSlaveTableData(connection, map, table, primaryKeyValue);
			}
		});
		return returnValues[0];
	}
	
	@SuppressWarnings("unchecked")
	private void saveSlaveTableData(Connection connection,Map<String, Object> map, TableDefinition table,Object masterPrimaryKeyValue) throws SQLException {
		List<TableDefinition> children=table.getSlaveTables();
		Object slaves=map.get(Constants.SLAVE_PROPERTY);
		if(children==null || children.size()==0 || slaves==null){
			return;
		}
		Collection<Map<String,Object>> coll=(Collection<Map<String,Object>>)slaves;
		if(coll.size()==0)return;
		TableDefinition slave=children.get(0);
		for(Map<String,Object> child:coll){
			Object keyValue=child.get(Constants.PRIMARY_KEY_COLUMN);
			List<Object> values=new ArrayList<Object>();
			String sql=null;
			if(keyValue==null || keyValue.toString().equals("0")){
				keyValue=IDGenerator.getInstance().nextId();
				values.add(keyValue);
				sql=buildInsertSql(slave,values,child,Long.valueOf(masterPrimaryKeyValue.toString()));
			}else{
				sql=buildUpdateSql(slave,values,child);
			}
			PreparedStatement stmt=connection.prepareStatement(sql);
			for(int i=1;i<values.size()+1;i++){
				Object obj=values.get(i-1);
				stmt.setObject(i,obj);
			}
			stmt.execute();
			stmt.close();
		}
	}
	
	private String buildUpdateSql(TableDefinition table,List<Object> params,Map<String,Object> map){
		StringBuffer sb=new StringBuffer();
		sb.append("update "+table.getName()+" set ");
		int i=0;
		for(TableColumn col:table.getColumns()){
			i++;
			sb.append(" "+col.getName()+"=? ");
			params.add(map.get(col.getName().toLowerCase()));
			if(i<table.getColumns().size()){
				sb.append(",");				
			}
		}
		sb.append(" where "+Constants.PRIMARY_KEY_COLUMN+"=?");
		params.add(map.get(Constants.PRIMARY_KEY_COLUMN));
		return sb.toString();
	}
	
	private String buildInsertSql(TableDefinition table,List<Object> params,Map<String,Object> map,Long masterId){
		StringBuffer sb=new StringBuffer();
		StringBuffer values=new StringBuffer();
		sb.append("insert into "+table.getName()+"(");
		sb.append(Constants.PRIMARY_KEY_COLUMN+",");
		values.append("?,");
		if(masterId!=null){
			values.append("?,");
			sb.append(Constants.MASTER_ID+",");
			params.add(masterId);			
		}else{
			sb.append(Constants.PROCESS_PROMOTER+",");
			values.append("?,");
			params.add(EnvironmentUtils.getEnvironment().getLoginUser());						
		}
		for(TableColumn col:table.getColumns()){
			sb.append(col.getName());	
			params.add(map.get(col.getName().toLowerCase()));
			values.append("?");
			sb.append(",");				
			values.append(",");
		}
		sb.append(Constants.STATE_COLUMN);
		sb.append(")");
		values.append("?");
		params.add(FormState.InProgress.toString());
		return sb.toString()+" values("+values.toString()+")";
	}

	public String getClickScript(String actionId) {
		return null;
	}
}
